﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Configuration;
using System.Runtime.InteropServices;
using KC.DataAccess.MV6;
using KC.Logging;
using KC.ExtensionMethods;


namespace KC.Presentation.MV7
{
	public partial class SiteMaster : System.Web.UI.MasterPage
	{
		private DateTime started;
		public IP ip;
		public Session session;
		public Dictionary<string, string> values;
		public KC.Business.Blog.Utils.RequestType ReqType;
		protected MV6DataContext dc = new MV6DataContext(ConfigurationManager.ConnectionStrings["MV6"].ConnectionString);
		public Activity act;
		
		protected void Page_Init(object sender, EventArgs e)
		{
			started = DateTime.Now;
			ReqType = Business.Blog.Utils.RequestType.Invalid;
			ReqType = KC.Business.Blog.Utils.DetectRequestType(Request.RawUrl, out values);
			DetectIp();
			if (session == null) InitSession();
		}
		protected void Page_PreRender(object sender, EventArgs e)
		{
			lblTime.Text = "Your request ate " + (DateTime.Now - started).TotalMilliseconds.ToString("###,###") + " of my milliseconds.";
		}


		protected void Page_Load(object sender, EventArgs e)
		{
			#region Update Menu
			int ID = -1;
			string page = System.IO.Path.GetFileName(HttpContext.Current.Request.FilePath).ToLower();
			switch (page) {
				case "default.aspx": default: ID = 0; break;
				case "resume.aspx": ID = 1; break;
				case "search.aspx": ID = 2; break;
				case "archives.aspx": ID = 3; break;
				case "categories.aspx": ID = 4; break;
				case "tags.aspx": ID = 5; break;
				case "about.aspx": ID = 6; break;
				case "office.aspx": ID = 7; break;
				case "gallery.aspx": ID = 8; break;
				case "stats.aspx": ID = 9; break; }
			NavigationMenu.Items[ID].Text = "[ " + NavigationMenu.Items[ID].Text + " ]";
			#endregion Update Menu
	
			
			// Update IP and Session info
			session.dEnded = DateTime.Now;

			

			// Find Post ID to put into Activity object
			int? PostID = null;
			if (values.ContainsKey("id")) PostID = (int?)int.Parse(values["id"]);
			else if (values.ContainsKey("title"))
				try {
					PostID = (from p2 in dc.Posts
							  where p2.FriendlyName.ToLower() == values["title"].ToLower() 
							  select p2).First().ID; }
				catch { PostID = null; }
			
			LogActivity(ReqType == Business.Blog.Utils.RequestType.Post ? (int?)PostID : null);
			LogSearchResult();
			
            // TODO: Log User, activity and session objects
			lblTagline.Text = KC.Business.Humor.Taglines.GetMessage();
		}

		/// <summary>Detects the IP object connected to this Request's IP address. Creates one if none found. Puts the result into global ip object.</summary>
		private void DetectIp()
		{
			// Find any IP(s) matching this address
			var ips = from a in dc.IPs
					where a.Address == Request.UserHostAddress
					orderby a.LastAccess descending 
					select a;
			if (ips.Count() == 1) // Exactly one match; use it.
				ip = ips.First();
			else if (ips.Count() > 1) { // Multiple matches; error out and use the most recent one.
				Logger.Write("MV7","Duplicate IPs", "Multiple IPs detected with Address " + Request.UserHostAddress + "; using " + ips.First().ID.ToString(), Logger.Severity.Error);
				ip = ips.First();
				return; }
			if (ips.Count() == 0) { // No matches; add a new one
				ip = new IP();
				ip.Address = Request.UserHostAddress;
				try { ip.Domain = Request.UserHostName; }
				catch { }
				ip.FirstAccess = DateTime.Now;
				ip.Hits = 0;
				ip.isSpider = KC.Business.Net.utils.isSpider(Request.UserAgent, Request.UserHostAddress);
				dc.IPs.InsertOnSubmit(ip); }

			// Update IP
			ip.Hits++;
			ip.LastAccess = DateTime.Now;
			dc.SubmitChanges();

		}
		private void InitSession()
		{
			session = new Session();
			session.dStarted = DateTime.Now;
			session.dEnded = DateTime.Now;
			session.IPID = ip.ID;
			session.UID = null;
			dc.Sessions.InsertOnSubmit(session);
			dc.SubmitChanges();
		}
		public void LogActivity(int? PostID)
		{
			act = new Activity();
			act.SID = session.ID;
			act.DateTime = DateTime.Now;
			if (PostID != null) act.PID = PostID;
			dc.Activities.InsertOnSubmit(act);
			act.Request = Request.RawUrl;
			act.Referrer = Request.UrlReferrer == null ? null : Request.UrlReferrer.AbsoluteUri;
			dc.SubmitChanges();

			if (session.Activities.Count() > 1)
				for (int i = 0; i < session.Activities.Count(); i++)
					Console.Beep(4000,100);
		}
		private void LogSearchResult()
		{
			// Detect whether this is a search engine referrer
			if (Request.UrlReferrer == null || string.IsNullOrEmpty(Request.UrlReferrer.AbsoluteUri)) return;
			string 
				engine = null,
				query = null;
			if (!KC.Business.Net.utils.isSearchEngineReferral(Request.UrlReferrer, out engine, out query)) return;

			Console.Beep(2500, 100);
			SearchResult sr = new SearchResult();
			sr.Query = query;
			sr.Engine = engine;
			sr.FullURL = Request.UrlReferrer.AbsoluteUri;
			sr.BaseURL = Request.UrlReferrer.GetRootDomain();
			sr.datetime = DateTime.Now;
			sr.AID = act.ID;
			dc.SearchResults.InsertOnSubmit(sr);
			dc.SubmitChanges();
		}
	}
}